package com.xxx.bluetooth;


import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

import com.xxx.bluetooth.bean.BluetoothInfo;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;


/**
 * A simple {@link Fragment} subclass.
 *
 * @author hdz
 */
public class BleClientFragment extends Fragment implements View.OnClickListener, AdapterView.OnItemClickListener {
    private static final String TAG = "BleClientFragment";

    private BluetoothAdapter mBluetoothAdapter;

    private List<BluetoothInfo> mBtData;
    private List<String> mBtAddrList;
    private BluetoothInfoAdapter mBluetoothInfoAdapter;

    private BluetoothDevice mBluetoothDevice;
    private BluetoothGatt mBluetoothGatt;

    private TextView mTvBtAddress;
    private TextView mTvBtName;
    private MyHandler mHandler;


    private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            Logger.d(TAG + ", onLeScan: " + device.getName() + " " + device.getAddress() + " " + Thread.currentThread());
            Logger.d(TAG + ", onLeScan: " + Util.deviceType2Str(device.getType()) + " " + Util.bondState2Str(device.getBondState()));
            if (!mBtAddrList.contains(device.getAddress())) {
                mBtAddrList.add(device.getAddress());
                mBtData.add(new BluetoothInfo(device.getAddress(), device.getName(), rssi, device.getType(), device.getBondState()));
                mBluetoothInfoAdapter.notifyDataSetChanged();
            } else {
                int index = mBtAddrList.indexOf(device.getAddress());
                if (mBtData.get(index).getRssi() != rssi) {
                    mBtData.get(index).setRssi(rssi);
                    mBluetoothInfoAdapter.notifyDataSetChanged();
                }
            }
        }
    };
    private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
            super.onPhyUpdate(gatt, txPhy, rxPhy, status);
        }

        @Override
        public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
            super.onPhyRead(gatt, txPhy, rxPhy, status);
        }

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            Logger.e(TAG + ", BluetoothGattCallback,onConnectionStateChange: " + status + " " + newState + " " + Thread.currentThread().getName());
            if (status == BluetoothGatt.GATT_SUCCESS) {
                String address = gatt.getDevice().getAddress();
                String name = gatt.getDevice().getName();
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    sendMessage(0, gatt.getDevice());
                }
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            Logger.e(TAG + ", BluetoothGattCallback,onServicesDiscovered: " + status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (mBluetoothGatt.getService(Constant.SERVICE_UUID) != null) {
                    Logger.e("===============");
                }
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            Logger.e(TAG + ", BluetoothGattCallback,onCharacteristicRead: " + status);
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorRead(gatt, descriptor, status);
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
        }

        @Override
        public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
            super.onReliableWriteCompleted(gatt, status);
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            super.onReadRemoteRssi(gatt, rssi, status);
        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            super.onMtuChanged(gatt, mtu, status);
        }
    };


    public BleClientFragment() {
        // Required empty public constructor
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Logger.w(TAG + ", onAttach: ####");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Logger.w(TAG + ", onCreateView: ####");
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_ble_client, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Logger.w(TAG + ", onViewCreated: ####");
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Logger.w(TAG + ", onActivityCreated: ####");
        initView();
        init();
//        getContext().startService(new Intent(getContext(), BleClientService.class));
    }

    @Override
    public void onStart() {
        super.onStart();
        Logger.w(TAG + ", onStart: ####");
    }

    @Override
    public void onResume() {
        super.onResume();
        Logger.w(TAG + ", onResume: ####");
    }

    @Override
    public void onPause() {
        super.onPause();
        Logger.w(TAG + ", onPause: ####");
    }

    @Override
    public void onStop() {
        super.onStop();
        Logger.w(TAG + ", onStop: ####");
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        Logger.w(TAG + ", onHiddenChanged: " + hidden);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Logger.w(TAG + ", onDestroyView: ####");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Logger.w(TAG + ", onDestroy: ####");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Logger.w(TAG + ", onDetach: ####");
    }

    private void init() {
        if (getContext() != null) {
            BluetoothManager mBluetoothManager = (BluetoothManager) getContext().getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetoothAdapter = mBluetoothManager.getAdapter();
            mBtData = new LinkedList<BluetoothInfo>();
            mBluetoothInfoAdapter = new BluetoothInfoAdapter((LinkedList<BluetoothInfo>) mBtData, getContext());
            ListView listView = (ListView) getView().findViewById(R.id.bt_list);
            listView.setAdapter(mBluetoothInfoAdapter);
            listView.setOnItemClickListener(this);

            mBtAddrList = new ArrayList<String>();

            mHandler = new MyHandler(this);
        }

    }

    private void initView() {
        View view = getView();
        if (view != null) {
            Button startScanBtn = (Button) view.findViewById(R.id.start_scan_btn);
            startScanBtn.setOnClickListener(this);

            Button stopScanBtn = (Button) view.findViewById(R.id.stop_scan_btn);
            stopScanBtn.setOnClickListener(this);

            Button disconnectBtn = (Button) view.findViewById(R.id.disconnect_btn);
            disconnectBtn.setOnClickListener(this);

            Button discoverServicesBtn = (Button) view.findViewById(R.id.discover_services_btn);
            discoverServicesBtn.setOnClickListener(this);

            Button sendMsgBtn = (Button) view.findViewById(R.id.send_msg_btn);
            sendMsgBtn.setOnClickListener(this);

            mTvBtAddress = (TextView) view.findViewById(R.id.bleAddress);
            mTvBtName = (TextView) view.findViewById(R.id.bleName);
        }
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.start_scan_btn:
                startScan();
                break;
            case R.id.stop_scan_btn:
                stopScan();
                break;
            case R.id.disconnect_btn:
                if (mBluetoothGatt != null) {
                    mBluetoothGatt.disconnect();
                }
                break;
            case R.id.discover_services_btn:
                if (mBluetoothGatt != null) {
                    mBluetoothGatt.discoverServices();
                }
                break;
            case R.id.send_msg_btn:

                break;
            default:
                break;
        }
    }


    private void startScan() {
        if (mBluetoothAdapter != null) {
            mBluetoothAdapter.startLeScan(mLeScanCallback);
        }
    }

    private void stopScan() {
        if (mBluetoothAdapter != null) {
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Logger.v(TAG + ", onItemClick: address: " + mBtData.get(position).getAddress());
        // 根据蓝牙地址获取远程蓝牙设备对象
        mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(mBtAddrList.get(position));
        // 连接蓝牙
        mBluetoothGatt = mBluetoothDevice.connectGatt(getContext(), false, mGattCallback);

    }


    private void sendMessage(int what, Object obj) {
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        mHandler.sendMessage(msg);
    }


    private static class MyHandler extends Handler {
        private WeakReference<BleClientFragment> mWeakBleClientFragment;

        public MyHandler(BleClientFragment bleClientFragment) {
            mWeakBleClientFragment = new WeakReference<>(bleClientFragment);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 0) {
                BluetoothDevice device = (BluetoothDevice) msg.obj;
                mWeakBleClientFragment.get().mTvBtName.setText(device.getName());
                mWeakBleClientFragment.get().mTvBtAddress.setText(device.getAddress());
            }
        }
    }
}
